package com.ksyun.campus.metaserver.service.impl;

import com.ksyun.campus.metaserver.common.result.BaseResult;
import com.ksyun.campus.metaserver.entity.dto.req.WriteReqDto;
import com.ksyun.campus.metaserver.entity.meta.StatInfo;
import com.ksyun.campus.metaserver.entity.meta.tree.FileTreeManager;
import com.ksyun.campus.metaserver.service.SyncMetaService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * 元数据服务业务实现层
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SyncMetaServiceImpl implements SyncMetaService {

    private final FileTreeManager fileTreeManager;

    @Override
    public BaseResult<StatInfo> createFile(String fileSystemName, String path, StatInfo statInfo) {
        // 校验文件是否已经存在
        if (fileTreeManager.pathExists(fileSystemName, path)) {
            throw new RuntimeException(String.format("文件已存在，请勿重新创建 [path]: %s", path));
        }

        boolean createFileResult = fileTreeManager.addFile(fileSystemName, path, statInfo);
        if (!createFileResult) {
            throw new RuntimeException(String.format("父级目录不存在，拒绝创建 [path]: %s", path));
        }
        fileTreeManager.printFileTree(fileSystemName);
        return BaseResult.success(statInfo);
    }

    @Override
    public BaseResult<String> commitWrite(String fileSystemName, WriteReqDto writeReqDto) {
        StatInfo statInfo = writeReqDto.getStatInfo();
        long size = statInfo.getSize();
        if (size == -1) {
            // 文件写入失败了 删除目录
            fileTreeManager.deleteFile(fileSystemName, statInfo.getPath());
            throw new RuntimeException(String.format("文件写入失败，已删除文件 [path]:%s", statInfo.getPath()));
        }
        // 更新修改时间
        statInfo.setMtime(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        String path = statInfo.getPath();
        if (!fileTreeManager.updateFile(fileSystemName, path, statInfo)) {
            throw new RuntimeException(String.format("写文件提交失败 [path]: %s", path));
        }
        fileTreeManager.printFileTree(fileSystemName);
        return BaseResult.success("写文件提交成功");
    }

    @Override
    public BaseResult<StatInfo> mkdir(String fileSystemName, String path, StatInfo statInfo) {
        // 校验文件夹是否已经存在
        if (fileTreeManager.pathExists(fileSystemName, path)) {
            throw new RuntimeException(String.format("文件夹已存在，请勿重新创建 [path]: %s", path));
        }
        boolean mkdirResult = fileTreeManager.addFile(fileSystemName, path, statInfo);
        if (!mkdirResult) {
            throw new RuntimeException(String.format("父级目录不存在，拒绝创建 [path]: %s", path));
        }
        fileTreeManager.printFileTree(fileSystemName);
        return BaseResult.success(statInfo);
    }

    @Override
    public BaseResult<StatInfo> delete(String fileSystemName, String path) {
        // 找到当前路径对应的节点
        // 暂存statInfo
        StatInfo statInfo = fileTreeManager.findNode(fileSystemName, path);
        if (statInfo == null) {
            throw new RuntimeException(String.format("路径不存在，请检查路径是否正确 [path]: %s", path));
        }
        if (!fileTreeManager.deleteFile(fileSystemName, path)) {
            throw new RuntimeException(String.format("文件或文件夹删除异常 [path]: %s", path));
        }
        fileTreeManager.printFileTree(fileSystemName);
        return BaseResult.success(statInfo);
    }
    @Override
    public BaseResult<String> deleteErrorRecovery(String fileSystemName, StatInfo statInfo) {
        // 把元数据信息重新加入文件树
        fileTreeManager.addFile(fileSystemName, statInfo.getPath(), statInfo);
        return BaseResult.success("删除失败回调恢复文件树成功");
    }
}
